package org.zjt.rpc.util;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.zjt.rpc.domain.RpcMsgProto;

import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by Administrator on 2017/4/11.
 */
public class  InvokeMethodExecuter  {

    private static final String DELIMITER = ",";

    public static RpcMsgProto.msg createRpcMsgProto(Method m, Object[] Params  ){
        List accResult =Arrays.stream(m.getParameterTypes()).map( a -> a.getName() ).collect(Collectors.toList());
        String paramClass = String.join(DELIMITER,accResult);
        RpcMsgProto.msg.Builder builder =RpcMsgProto.msg.newBuilder();
        builder.setClassName(m.getDeclaringClass().getName());
        builder.setParam(JSONObject.toJSONString(Params));
        builder.setParamClassName(paramClass);
        builder.setMethodName(m.getName());
        return builder.build();
    }


    public static Object exec(RpcMsgProto.msg msg)throws Exception{
        Class cls = handleSingleClss(BeanRelationTree.getBeanImple(msg.getClassName() ));

        List<Class>  paramClass = handleMethodParamClss( msg.getParamClassName() );
        if (paramClass == null || paramClass.isEmpty() ){
            Method v1 =cls.getDeclaredMethod(msg.getMethodName());
            return v1.invoke(cls.newInstance());
        } else{
            Class[] classes = new Class[paramClass.size()];
            paramClass.toArray(classes);
            Method v1 = cls.getDeclaredMethod(msg.getMethodName(),classes);
            return v1.invoke(cls.newInstance(), handleMethodParam(msg.getParam(),paramClass));
        }
    }


    public static void main(String[] args)throws Exception{
//        System.err.println(exec(createRpcMsgProto()));
    }


    //boolean byte char short Int long float double void
    public static List<Class>  handleMethodParamClss(String className)throws Exception{
        className = className != null && !className.trim().equals("") ? className.trim() : null;
        if (className == null) return null ;
        String[] array = className.split(DELIMITER);
        List<Class> classes = new ArrayList<>(array.length);
        for (String c : array){
            switch (c){
                case "int":  classes.add(int.class); break;
                case "double": classes.add( double.class);break;
                case "boolean": classes.add( boolean.class);break;
                case "byte": classes.add( byte.class);break;
                case "char": classes.add( char.class);break;
                case "short": classes.add( short.class);break;
                case "long": classes.add( long.class);break;
                case "float": classes.add( float.class);break;
                case "void": classes.add(void.class);break;
                default:
                    classes.add( Class.forName( c ));
            }
        }
        if(classes.stream().allMatch( a -> a.equals(void.class) ))
            return null;
        return classes;
    }


    public static Class handleSingleClss(String className)throws Exception{
       List<Class> classes = handleMethodParamClss(className);
        Class cl= classes != null && !classes.isEmpty() ? classes.get(0) : null ;
        if (cl == null)
            throw new NullPointerException("class is null");
        return cl;
    }


    public static Object[] handleMethodParam(String params ,List<Class>  paramClass)throws Exception{
        if(params== null || params.trim().equals(""))
            throw new NullPointerException("params is null");
        JSONArray jsonArray = JSONObject.parseArray(params);
        return jsonArray.toArray();
    }


}
